package cn.com.easy.utils;

import java.text.ParseException;
import java.util.Date;
import java.util.Map;

import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 定时任务工具类
 * 
 * @author nibili 2016年12月28日
 * 
 */
public class QuartzUtils {

	private static Logger LOG = LoggerFactory.getLogger(QuartzUtils.class);

	private static SchedulerFactory gSchedulerFactory = new StdSchedulerFactory();

	private static String JOB_GROUP_NAME = "DEFAULT_JOBGROUP_NAME";

	private static String TRIGGER_GROUP_NAME = "DEFAULT_TRIGGERGROUP_NAME";

	public static void main(String[] args) {
		try {
			QuartzUtils.addJob("my", new Runnable() {

				@Override
				public void run() {
					for (int i = 0; i < 10; i++) {
						System.out.println("run my job!");
					}

				}
			}, "00 12 12 * * ?");

			QuartzUtils.addJob("my1", new Runnable() {

				@Override
				public void run() {
					for (int i = 0; i < 10; i++) {
						System.out.println("run my job!-----11");
					}

				}
			}, "00 12 12 * * ?");

			Date date = new Date();
			date = DateUtils.addMinutes(date, 1);
			QuartzUtils.addJob("my2", new Runnable() {

				@Override
				public void run() {
					for (int i = 0; i < 10; i++) {
						System.out.println("run my job!-----2");
					}

				}
			}, date);

			String[] jobNames = getJobnames();
			for (String tempString : jobNames) {
				System.out.println(tempString);
			}

		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * 获取当前已存在的任务名集合
	 * 
	 * @return
	 * @throws SchedulerException
	 * @auth nibili 2018年6月29日
	 */
	public static String[] getJobnames() throws SchedulerException {
		return gSchedulerFactory.getScheduler().getJobNames(JOB_GROUP_NAME);
	}

	/**
	 * 添加一次性定时作业
	 * 
	 * @param jobName
	 * @param runnable
	 * @param date
	 * @throws SchedulerException
	 * @throws ParseException
	 * @author nibili 2017年8月24日
	 */
	public static void addJob(String jobName, Runnable runnable, Date date) throws SchedulerException, ParseException {
		String dateFormat = "ss mm HH dd MM ? yyyy";
		String cronExpretion = DateUtils.formatDate(date, dateFormat);
		QuartzUtils.addJob(jobName, runnable, cronExpretion);
	}

	/**
	 * 添加作业
	 * 
	 * @param jobName
	 * @param runnable
	 * @param cronExpretion
	 * @throws SchedulerException
	 * @throws ParseException
	 * @auth nibili 2015-3-30
	 */
	public static void addJob(String jobName, Runnable runnable, String cronExpretion) throws SchedulerException, ParseException {

		Scheduler sched = gSchedulerFactory.getScheduler();
		JobDetail jobDetail = new JobDetail(jobName, JOB_GROUP_NAME, MyJobProxy.class);
		jobDetail.getJobDataMap().put("myjob", runnable);
		CronTrigger trigger = new CronTrigger(jobName, TRIGGER_GROUP_NAME);
		trigger.setCronExpression(cronExpretion);
		sched.scheduleJob(jobDetail, trigger);
		// boolean isShutdown = sched.isShutdown();
		boolean isStarted = sched.isStarted();
		if (isStarted == false) {
			sched.start();
		}

	}

	public static class MyJobProxy implements Job {

		private Runnable job = null;

		public void execute(JobExecutionContext context) throws JobExecutionException {
			JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
			this.job = (Runnable) jobDataMap.get("myjob");
			this.job.run();
		}
	}

	/**
	 * 
	 * add a job
	 * 
	 * @param jobName
	 *            job name
	 * @param cls
	 *            job class
	 * @param cronExpretion
	 *            crond expression
	 * @throws SchedulerException
	 * @throws ParseException
	 */
	public static void addJob(String jobName, Class<?> cls, String cronExpretion) throws SchedulerException, ParseException {

		Scheduler sched = gSchedulerFactory.getScheduler();
		JobDetail jobDetail = new JobDetail(jobName, JOB_GROUP_NAME, cls);
		CronTrigger trigger = new CronTrigger(jobName, TRIGGER_GROUP_NAME);
		trigger.setCronExpression(cronExpretion);
		sched.scheduleJob(jobDetail, trigger);
		boolean isStarted = sched.isStarted();
		if (isStarted == false) {
			sched.start();
		}

	}

	/**
	 * add a job
	 * 
	 * @param jobName
	 *            job name
	 * @param jobGroupName
	 *            job group name
	 * @param triggerName
	 *            trigger name
	 * @param triggerGroupName
	 *            trigger group name
	 * @param jobClass
	 *            job class
	 * @param cronExpretion
	 *            crond expression
	 * @param params
	 *            to set on context
	 * @throws SchedulerException
	 * @throws ParseException
	 */

	public static void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class<?> jobClass, String cronExpretion, Map<String, Object> params)
			throws SchedulerException, ParseException {

		Scheduler sched = gSchedulerFactory.getScheduler();
		JobDetail jobDetail = new JobDetail(jobName, jobGroupName, jobClass);
		CronTrigger trigger = new CronTrigger(triggerName, triggerGroupName);
		trigger.setCronExpression(cronExpretion);
		// set params to context
		if (params != null) {
			for (Map.Entry<String, Object> entry : params.entrySet()) {
				sched.getContext().put(entry.getKey(), entry.getValue());
			}
		}
		sched.scheduleJob(jobDetail, trigger);
		boolean isStarted = sched.isStarted();
		if (isStarted == false) {
			sched.start();
		}
		LOG.debug("###Add Job Succeed!!jobName = [{}],jobGroupName = [{}],triggerName = [{}]," + "triggerGroupName = [{}],cronExp = [{}] ###", jobName, jobGroupName, triggerName,
				triggerGroupName, cronExpretion);

	}

	/**
	 * modify job
	 * 
	 * @param jobName
	 * @param cronExpretion
	 * @throws SchedulerException
	 * @throws ParseException
	 */
	public static void modifyJobcronExpretion(String jobName, String cronExpretion) throws SchedulerException, ParseException {

		Scheduler sched = gSchedulerFactory.getScheduler();
		CronTrigger trigger = (CronTrigger) sched.getTrigger(jobName, TRIGGER_GROUP_NAME);
		if (trigger == null) {
			return;
		}
		String oldcronExpretion = trigger.getCronExpression();
		if (!oldcronExpretion.equalsIgnoreCase(cronExpretion)) {
			JobDetail jobDetail = sched.getJobDetail(jobName, JOB_GROUP_NAME);
			Class<?> objJobClass = jobDetail.getJobClass();
			removeJob(jobName);
			addJob(jobName, objJobClass, cronExpretion);
		}

	}

	/**
	 * modify job cronExpretion
	 * 
	 * @param triggerName
	 * @param triggerGroupName
	 * @param cronExpretion
	 * @throws SchedulerException
	 * @throws ParseException
	 */
	public static void modifyJobcronExpretion(String triggerName, String triggerGroupName, String cronExpretion) throws SchedulerException, ParseException {

		Scheduler sched = gSchedulerFactory.getScheduler();
		CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerName, triggerGroupName);
		if (trigger == null) {
			return;
		}
		String oldcronExpretion = trigger.getCronExpression();
		if (!oldcronExpretion.equalsIgnoreCase(cronExpretion)) {
			CronTrigger ct = (CronTrigger) trigger;
			// 修改时间
			ct.setCronExpression(cronExpretion);
			// 重启触发器
			sched.resumeTrigger(triggerName, triggerGroupName);
		}

	}

	/**
	 * remove a job
	 * 
	 * @param jobName
	 * @throws SchedulerException
	 */
	public static void removeJob(String jobName) throws SchedulerException {

		Scheduler sched = gSchedulerFactory.getScheduler();
		sched.pauseTrigger(jobName, TRIGGER_GROUP_NAME);// 停止触发器
		sched.unscheduleJob(jobName, TRIGGER_GROUP_NAME);// 移除触发器
		sched.deleteJob(jobName, JOB_GROUP_NAME);// 删除任务

	}

	/**
	 * remove a job
	 * 
	 * @param jobName
	 * @param jobGroupName
	 * @param triggerName
	 * @param triggerGroupName
	 * @throws SchedulerException
	 */
	public static void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) throws SchedulerException {

		Scheduler sched = gSchedulerFactory.getScheduler();
		sched.pauseTrigger(triggerName, triggerGroupName);// stop trigger
		sched.unscheduleJob(triggerName, triggerGroupName);// remove trigger
		sched.deleteJob(jobName, jobGroupName);// delete job
		LOG.debug("###Remove Job Succeed!!jobName = [{}],jobGroupName = [{}],triggerName = [{}]," + "triggerGroupName = [{}],cronExp = [{}] ###", jobName, jobGroupName,
				triggerName, triggerGroupName);

	}

	/**
	 * start all jobs
	 * 
	 * @throws SchedulerException
	 */
	public static void startJobs() throws SchedulerException {

		Scheduler sched = gSchedulerFactory.getScheduler();
		sched.start();

	}

	/**
	 * shutdown all jobs
	 * 
	 * @throws SchedulerException
	 */
	public static void shutdownJobs() throws SchedulerException {

		Scheduler sched = gSchedulerFactory.getScheduler();
		boolean isStarted = sched.isStarted();
		if (isStarted == false) {
			sched.start();
		}

	}
}